﻿using QuickOpen.HotKey;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml;

namespace QuickOpen
{


    public partial class Form1 : Form
    {
        private float xPos = 0;
        private float yPos = 0;
        private Point startPos;
        private Button currentBtn;      //当前选中按钮
        private int btnIndex = 0;
        private Dictionary<string, string> dictBtnAndSrc = new Dictionary<string, string>();
        List<Button> buttonList = new List<Button>();
        Dictionary<string, MoveControl> btnMoveCtlDic = new Dictionary<string, MoveControl>();

        /// <summary>
        /// 鼠标按下
        /// </summary>
        private bool mouseIsDown = false;
        private Rectangle mouseRect = Rectangle.Empty;

        /// <summary>
        /// 窗体大小
        /// </summary>
        private Size frmSize;

        XmlDocument xmldoc;
        XmlElement xmlelem;


        private Rectangle selectionRectangle;
        private Point mouseDownLocation;


        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        public Form1()
        {
            this.KeyPreview = true;
            this.KeyDown += new KeyEventHandler(Form1_KeyDown);

            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                //注册热键
                HotKeyManager.RegisterHotKey(base.Handle, 100, (uint)KeyModifiers.Control, Keys.D3);

                xmldoc = new XmlDocument();
                //如果xml不存在，返回
                if (!File.Exists("./config.xml"))
                    return;
                //初始化数据
                xmldoc.Load("./config.xml");

                XmlNode frmNode = xmldoc.SelectSingleNode("//FormSetting/Size");
                Regex reg = new Regex(@"\d+");
                MatchCollection matchCollection = reg.Matches(frmNode.InnerText);

                this.ClientSize = new Size(int.Parse(matchCollection[0].Value), int.Parse(matchCollection[1].Value));

                frmSize = this.Size;

                //随后获取屏幕的分辨率，也就是显示器屏幕的大小。
                int xWidth = SystemInformation.PrimaryMonitorSize.Width;//获取显示器屏幕宽度
                int yHeight = SystemInformation.PrimaryMonitorSize.Height;//高度
                                                                          //然后定义窗口位置，以主窗体为例
                this.Location = new Point((xWidth - this.Size.Width) / 2, (yHeight - this.Size.Height) / 2);//这里需要再减去窗体本身的宽度和高度的一半

                //this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;

                //从xml加载按钮
                InitFastBtn();
            }
            catch (Exception ex)
            {
                MessageBox.Show("load : " + ex.Message);
            }
        }
        Point oriPostion;

        #region 鼠标绘图

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                oriPostion = e.Location;
                mouseDownLocation = e.Location;
                this.Invalidate();
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                int x = Math.Min(e.X, mouseDownLocation.X);
                int y = Math.Min(e.Y, mouseDownLocation.Y);
                int width = Math.Abs(e.X - mouseDownLocation.X);
                int height = Math.Abs(e.Y - mouseDownLocation.Y);
                selectionRectangle = new Rectangle(x, y, width, height);

                // 在此处执行框选内容的操作，例如复制或删除
                //foreach (var item in buttonList)
                //{
                //    var itemX = item.Location.X;
                //    var itemY = item.Location.Y;
                //    //元素是否在框选内
                //    if (itemX > x && itemX < (x + width) && itemY > y && itemY < (y + height))
                //    {

                //        btnMoveCtlDic[item.Name].MouseClickBorder(null, null);
                //        Console.WriteLine($"contains {item.Text}");

                //    }
                //}
                selectionRectangle = Rectangle.Empty;
                this.Invalidate();
            }
        }


        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            this.lblLog.Text = $"X: {e.Location.X}\n";
            this.lblLog.Text += $"Y: {e.Location.Y}";

            //if (mouseIsDown)
            //    ResizeToRectangle(e.Location);

            if (e.Button == MouseButtons.Left)
            {
                int x = Math.Min(e.X, mouseDownLocation.X);
                int y = Math.Min(e.Y, mouseDownLocation.Y);
                int width = Math.Abs(e.X - mouseDownLocation.X);
                int height = Math.Abs(e.Y - mouseDownLocation.Y);
                selectionRectangle = new Rectangle(x, y, width, height);
                this.Invalidate();


                ////鼠标拖动，带动标记的按钮移动
                //foreach (var dicItem in btnMoveCtlDic)
                //{
                //    if (dicItem.Value.fc == default)
                //    {
                //        continue;
                //    }
                //    //边框可见，说明支持拖动
                //    if (dicItem.Value.fc.Visible)
                //    {
                //        //dicItem.Value.ResetLocation(e.X - oriPostion.X, e.Y - oriPostion.Y);

                //        //oriPostion = e.Location;
                //        //dicItem.Value.pPoint = oriPostion;
                //        //dicItem.Value.MouseUpBorder(null, null);
                //        //dicItem.Value.fc.Draw();
                //        //dicItem.Value.MouseMoveCtl(sender, e);

                //        //this.Invalidate();
                //    }
                //}
            }
        }


        #endregion

        //重写WndProc()方法，通过监视系统消息，来调用过程
        protected override void WndProc(ref Message m)
        {
            //如果m.Msg的值为0x0312那么表示用户按下了热键
            const int WM_HOTKEY = 0x0312;

            //按快捷键    
            switch (m.Msg)
            {
                case WM_HOTKEY:
                    switch (m.WParam.ToInt32())
                    {
                        case 100:
                            if (base.Visible)
                            {
                                //如果此窗体处于非激活状态，隐藏
                                if (GetForegroundWindow() == this.Handle)
                                    HideForm();
                                else
                                    base.Activate();
                            }
                            else
                            {
                                ShowForm();
                            }
                            break;
                    }
                    break;
            }
            base.WndProc(ref m);
        }
        private void ShowForm()
        {

            //任务栏区显示图标
            base.Visible = true;
            //还原窗体显示    
            WindowState = FormWindowState.Normal;
            //激活窗体并给予它焦点
            this.Activate();

            //托盘区图标隐藏
            //notifyIcon1.Visible = false;
        }
        private void HideForm()
        {
            //你一点都不安静
            //notifyIcon1.ShowBalloonTip(10);

            //隐藏任务栏区图标
            base.Visible = false;
            //this.ShowInTaskbar = false;

            //图标显示在托盘区
            notifyIcon1.Visible = true;
        }

        /// <summary>
        /// 单击托盘图标
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NotifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ShowForm();
            }
        }

        /// <summary>
        /// 判断是否最小化,然后显示托盘
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
                HideForm();
        }

        /// <summary>
        /// 从xml加载按钮
        /// </summary>
        private void InitFastBtn()
        {

            XmlNode xmlRoot = xmldoc.SelectSingleNode("//btnContainer");

            foreach (XmlNode item in xmlRoot.ChildNodes)
            {
                Button btn1 = new Button();
                btn1.Name = item.Name;

                btn1.Text = item.SelectSingleNode("Text").InnerText;
                //正则：匹配数字
                Regex reg = new Regex(@"\d+");

                //位置
                MatchCollection matchCollection = reg.Matches(item.SelectSingleNode("Location").InnerText);
                btn1.Location = new Point(int.Parse(matchCollection[0].Value), int.Parse(matchCollection[1].Value));
                //大小
                try
                {
                    matchCollection = reg.Matches(item.SelectSingleNode("Size").InnerText);
                    btn1.Size = new Size(Convert.ToInt32(matchCollection[0].Value), Convert.ToInt32(matchCollection[1].Value));
                }
                catch (Exception)
                {
                    btn1.Width = 100;
                    btn1.Height = 50;
                }

                btn1.ForeColor = ColorTranslator.FromHtml(item.SelectSingleNode("ForeColor").InnerText);
                btn1.BackColor = ColorTranslator.FromHtml(item.SelectSingleNode("BackColor").InnerText);


                buttonList.Add(btn1);
                dictBtnAndSrc.Add(btn1.Name, item.SelectSingleNode("Src").InnerText);


                BindBtnEvent(btn1);
            }
        }

        /// <summary>
        /// 窗口关闭时，保存数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            SaveInfo();
            //卸载热键
            HotKeyManager.UnregisterHotKey(Handle, 100);
            //清除托盘图标
            notifyIcon1.Visible = false;
        }
        /// <summary>
        /// 保存
        /// </summary>
        private void SaveInfo()
        {
            xmldoc = new XmlDocument();

            XmlElement rootElement = xmldoc.CreateElement("root");
            xmldoc.AppendChild(rootElement);

            //窗体集合
            XmlElement formSettingElement = xmldoc.CreateElement("FormSetting");
            rootElement.AppendChild(formSettingElement);
            //按钮集合
            XmlElement btnContainerElement = xmldoc.CreateElement("btnContainer");
            rootElement.AppendChild(btnContainerElement);

            //保存窗体大小
            XmlElement frm = xmldoc.CreateElement("Size");
            //如果窗体最小化了，保存最小化前的窗体大小
            if (WindowState == FormWindowState.Minimized)
                frm.InnerText = frmSize.ToString();
            else
            {
                frm.InnerText = this.Size.ToString();
            }
            xmldoc.SelectSingleNode("//FormSetting").AppendChild(frm);

            //保存按钮
            foreach (Control item in Controls)
            {
                //如果此控件是fastBtn，保存它的信息
                if (item.Name.StartsWith("fastBtn"))
                {
                    SaveFastBtnInfo(item);
                }
            }

            xmldoc.Save("./config.xml");
        }
        /// <summary>
        /// 保存按钮信息
        /// </summary>
        /// <param name="fastBtnControl"></param>
        private void SaveFastBtnInfo(Control fastBtnControl)
        {
            //加入一个根元素
            xmlelem = xmldoc.CreateElement(fastBtnControl.Name);
            xmlelem.SetAttribute("name", fastBtnControl.Name);
            //显示文本
            XmlElement nodeText = xmldoc.CreateElement("Text");
            nodeText.InnerText = fastBtnControl.Text;
            xmlelem.AppendChild(nodeText);
            //位置
            XmlElement nodeLocation = xmldoc.CreateElement("Location");
            nodeLocation.InnerText = fastBtnControl.Location.ToString();
            xmlelem.AppendChild(nodeLocation);
            //大小
            XmlElement nodeSize = xmldoc.CreateElement("Size");
            nodeSize.InnerText = fastBtnControl.Size.ToString();
            xmlelem.AppendChild(nodeSize);
            //链接
            XmlElement nodeSrc = xmldoc.CreateElement("Src");
            nodeSrc.InnerText = dictBtnAndSrc[fastBtnControl.Name];
            xmlelem.AppendChild(nodeSrc);
            //前景色
            XmlElement nodeForeColor = xmldoc.CreateElement("ForeColor");
            nodeForeColor.InnerText = fastBtnControl.ForeColor.ToArgb().ToString();
            xmlelem.AppendChild(nodeForeColor);
            //背景色
            XmlElement nodeBackColor = xmldoc.CreateElement("BackColor");
            nodeBackColor.InnerText = fastBtnControl.BackColor.ToArgb().ToString();
            xmlelem.AppendChild(nodeBackColor);

            xmldoc.DocumentElement.SelectSingleNode("btnContainer").AppendChild(xmlelem);
            //xmldoc.SelectSingleNode("//btnContainer");
        }
        /// <summary>
        /// 创建一个快速启动按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CreateABtnToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateABtn("空内容");
        }
        /// <summary>
        /// 创建一个按钮
        /// </summary>
        /// <param name="btnUrl"></param>
        void CreateABtn(string btnUrl)
        {
            Button btn1 = new Button();

            btn1.Name = "fastBtn" + btnIndex++;
            btn1.Width = 100;
            btn1.Height = 50;
            btn1.Font = new Font("宋体", 10);
            var splitPaths = btnUrl.Split('\\');
            btn1.Text = splitPaths[splitPaths.Length - 1];
            btn1.Location = this.PointToClient(Control.MousePosition);
            btn1.Location = new Point(btn1.Location.X - 50, btn1.Location.Y - 25);

            //判断这个btn1.Name 是否已经存在于字典
            while (dictBtnAndSrc.ContainsKey(btn1.Name))
            {
                btn1.Name = "fastBtn" + btnIndex++;
            }
            dictBtnAndSrc.Add(btn1.Name, btnUrl);
            buttonList.Add(btn1);

            BindBtnEvent(btn1);

            //添加完按钮后，保存数据
            this.SaveInfo();

        }
        /// <summary>
        /// 给按钮绑定事件
        /// </summary>
        private void BindBtnEvent(Button btn1)
        {

            var mctl = new MoveControl(btn1);
            btnMoveCtlDic.Add(btn1.Name, mctl);
            btn1.MouseDown += BtnMouseDown;
            btn1.MouseClick += BtnMouseClick;
            this.Controls.Add(btn1);
        }

        /// <summary>
        /// 鼠标点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnMouseDown(object sender, MouseEventArgs e)
        {
            try
            {
                currentBtn = sender as Button;

                xPos = e.X;//当前x坐标.
                yPos = e.Y;//当前y坐标.
                startPos = currentBtn.Location; //记录点击开始的位置


                //点击右键,将contextMenuStripBtn赋给此按钮
                if (e.Button == MouseButtons.Right)
                {
                    currentBtn.ContextMenuStrip = contextMenuStripBtn;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void BtnMouseClick(object sender, MouseEventArgs e)
        {
            try
            {
                //点击左键
                if (e.Button == MouseButtons.Left)
                {
                    //判断点击之前是否拖动
                    if (Math.Sqrt(Math.Pow(currentBtn.Location.X - startPos.X, 2) + Math.Pow(currentBtn.Location.Y - startPos.Y, 2)) < 1)
                    {
                        //避免点击后，控件跟着鼠标瞬移
                        currentBtn.Capture = false;
                        System.Diagnostics.Process.Start(dictBtnAndSrc[currentBtn.Name]);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //右键打开菜单后触发
        private void contextMenuStrip1_Opened(object sender, EventArgs e)
        {
            //当前选中按钮
            currentBtn = contextMenuStripBtn.SourceControl as Button;

            //给默认名字
            toolStripTextBoxName.Text = contextMenuStripBtn.SourceControl.Text;
            //默认链接
            toolStripTextBoxHref.Text = dictBtnAndSrc[currentBtn.Name];
        }
        /// <summary>
        /// 名字：鼠标离开时更改
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripTextBoxName_TextChanged(object sender, EventArgs e)
        {
            try
            {
                //更改控件名字
                currentBtn.Text = toolStripTextBoxName.Text;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        //选择启动项
        private void ToolStripMenuItemFastSelect_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dialog = new OpenFileDialog();
                dialog.Multiselect = true;//该值确定是否可以选择多个文件
                dialog.Title = "请选择文件夹";
                dialog.Filter = "所有文件(*.*)|*.*";
                if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    dictBtnAndSrc[currentBtn.Name] = dialog.FileName;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 链接： 鼠标离开可见项部分
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripTextBoxHref_TextChanged(object sender, EventArgs e)
        {
            dictBtnAndSrc[currentBtn.Name] = toolStripTextBoxHref.Text;
        }
        /// <summary>
        /// 删除这个按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 删除ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult MsgBoxResult = MessageBox.Show("你确定要删除吗？", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);//定义对话框的按钮式样
                                                                                                                                                                //点击了确认
            if (MsgBoxResult == DialogResult.Yes)
            {
                //删除按钮
                ToolStripMenuItem toolStripMenuItem = sender as ToolStripMenuItem;
                ContextMenuStrip contextMenuStrip = toolStripMenuItem.Owner as ContextMenuStrip;
                Button btn = contextMenuStrip.SourceControl as Button;

                dictBtnAndSrc.Remove(btn.Name);
                buttonList.Remove(btn);

                this.Controls.Remove(btn);
                //删除父控件
                foreach (Control ct in this.Controls)
                {
                    if (ct.Name == string.Concat("FrameControl", btn.Name))
                    {
                        this.Controls.Remove(ct);
                        break;
                    }
                }

            }
        }

        private void 背景色更改ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog ColorForm = new ColorDialog();
            if (ColorForm.ShowDialog() == DialogResult.OK)
            {
                Color GetColor = ColorForm.Color;
                //GetColor就是用户选择的颜色，接下来就可以使用该颜色了
                currentBtn.BackColor = GetColor;
            }
        }

        private void 字体颜色ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //colorDialog1 ColorForm = new colorDialog1();
            if (colorDialog1.ShowDialog() == DialogResult.OK)
            {
                Color GetColor = colorDialog1.Color;
                //GetColor就是用户选择的颜色，接下来就可以使用该颜色了
                currentBtn.ForeColor = GetColor;
            }
        }

        /// <summary>
        /// 托盘：退出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveInfo();
            this.Close();
        }
        /// <summary>
        /// 单击窗体时，刷新空间，目的为了把按钮放大缩小标识隐藏
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Click(object sender, EventArgs e)
        {
            this.Refresh();
        }




        private void insertToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dbForm = new DBAssistant();
            dbForm.StartPosition = FormStartPosition.CenterScreen;
            dbForm.Show();
        }

        private void 数据库ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            var dbForm = new DBAssistant();
            dbForm.StartPosition = FormStartPosition.CenterScreen;
            dbForm.Show();
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {

            if (e.Control && e.KeyCode == Keys.V)
            {
                // 在这里添加 Ctrl+V 组合键被按下时要执行的代码
                // 例如，可以调用粘贴方法：
                //textBox1.Paste();

                var urlContent = string.Empty;
                if (Clipboard.ContainsText())
                {
                    urlContent = Clipboard.GetText();
                }
                //创建按钮
                CreateABtn(urlContent);
                e.Handled = true; // 防止其他控件继续处理此事件
            }
        }


        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            if (selectionRectangle != Rectangle.Empty)
            {
                ControlPaint.DrawFocusRectangle(e.Graphics, selectionRectangle);
            }
        }

    }
}
